package com.yc.cloud.admin.service.impl;

import com.yc.cloud.common.orm.CommonPage;
import com.yc.cloud.admin.dto.request.AlgStrategyCreateReqDTO;
import com.yc.cloud.admin.dto.request.AlgStrategyUpdateReqDTO;
import com.yc.cloud.admin.vo.AlgStrategyVo;
import com.yc.cloud.entity.AlgStrategy;
import com.yc.cloud.mapper.AlgStrategyMapper;
import com.yc.cloud.mapper.UmsAdminMapper;
import com.yc.cloud.admin.service.AlgStrategyService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yc.cloud.common.basic.dto.BasePageReqDTO;
import com.yc.cloud.common.basic.exception.Asserts;
import com.yc.cloud.entity.AlgStrategyAlgorithm;
import com.yc.cloud.entity.AlgStrategyDevice;
import com.yc.cloud.entity.AlgStrategyDeviceGroup;
import com.yc.cloud.entity.AlgStrategyRule;
import com.yc.cloud.mapper.AlgStrategyAlgorithmMapper;
import com.yc.cloud.mapper.AlgStrategyDeviceMapper;
import com.yc.cloud.mapper.AlgStrategyDeviceGroupMapper;
import com.yc.cloud.mapper.AlgStrategyRuleMapper;
import com.yc.cloud.admin.dto.request.AlgStrategyApplyReqDTO;
import com.yc.cloud.admin.vo.AlgAlgorithmVo;
import com.yc.cloud.admin.service.AlgAlgorithmService;
import com.yc.cloud.api.enums.PublishStatusEnum;
import com.yc.cloud.entity.UmsAdmin;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import cn.hutool.core.util.StrUtil;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 算法策略表 服务实现类
 * </p>
 *
 * @author kinggu
 * @since 2025-07-15
 */
@Service
public class AlgStrategyServiceImpl extends ServiceImpl<AlgStrategyMapper, AlgStrategy> implements AlgStrategyService {

    @Resource
    private AlgStrategyAlgorithmMapper algStrategyAlgorithmMapper;
    @Resource
    private AlgStrategyDeviceMapper algStrategyDeviceMapper;
    @Resource
    private AlgStrategyDeviceGroupMapper algStrategyDeviceGroupMapper;
    @Resource
    private AlgStrategyRuleMapper algStrategyRuleMapper;
    @Resource
    private AlgAlgorithmService algAlgorithmService;

    @Resource
    private UmsAdminMapper umsAdminMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean create(AlgStrategyCreateReqDTO createReqDTO) {
        // 1. 保存策略基本信息
        AlgStrategy entity = new AlgStrategy();
        BeanUtils.copyProperties(createReqDTO, entity);
        save(entity);

        // 2. 处理与算法的关联关系
        // if (!CollectionUtils.isEmpty(createReqDTO.getAlgorithmIds())) {
        // Long strategyId = entity.getId();
        // for (Long algorithmId : createReqDTO.getAlgorithmIds()) {
        // AlgStrategyAlgorithm association = new AlgStrategyAlgorithm();
        // association.setStrategyId(strategyId);
        // association.setAlgorithmId(algorithmId);
        // algStrategyAlgorithmMapper.insert(association);
        // }
        // }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(AlgStrategyUpdateReqDTO updateReqDTO) {
        // 1. 更新策略基本信息
        AlgStrategy entity = new AlgStrategy();
        BeanUtils.copyProperties(updateReqDTO, entity);
        updateById(entity);

        // 2. 更新与算法的关联关系 (先删后插)
        // 2.1 删除旧的关联
        QueryWrapper<AlgStrategyAlgorithm> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(AlgStrategyAlgorithm.StrategyId, updateReqDTO.getId());
        algStrategyAlgorithmMapper.delete(queryWrapper);

        // 2.2 插入新的关联
        if (!CollectionUtils.isEmpty(updateReqDTO.getAlgorithmIds())) {
            for (Long algorithmId : updateReqDTO.getAlgorithmIds()) {
                AlgStrategyAlgorithm association = new AlgStrategyAlgorithm();
                association.setStrategyId(updateReqDTO.getId());
                association.setAlgorithmId(algorithmId);
                algStrategyAlgorithmMapper.insert(association);
            }
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean apply(AlgStrategyApplyReqDTO applyReqDTO) {
        Long strategyId = applyReqDTO.getStrategyId();

        // 1. 处理与设备的关联
        // 1.1 删除旧的设备关联
        QueryWrapper<AlgStrategyDevice> deviceQueryWrapper = new QueryWrapper<>();
        deviceQueryWrapper.eq(AlgStrategyDevice.StrategyId, strategyId);
        algStrategyDeviceMapper.delete(deviceQueryWrapper);

        // 1.2 插入新的设备关联
        if (!CollectionUtils.isEmpty(applyReqDTO.getDeviceIds())) {
            for (Long deviceId : applyReqDTO.getDeviceIds()) {
                AlgStrategyDevice association = new AlgStrategyDevice(null, strategyId, deviceId);
                algStrategyDeviceMapper.insert(association);
            }
        }

        // 2. 处理与设备分组的关联
        // 2.1 删除旧的设备分组关联
        QueryWrapper<AlgStrategyDeviceGroup> groupQueryWrapper = new QueryWrapper<>();
        groupQueryWrapper.eq(AlgStrategyDeviceGroup.StrategyId, strategyId);
        algStrategyDeviceGroupMapper.delete(groupQueryWrapper);

        // 2.2 插入新的设备分组关联
        if (!CollectionUtils.isEmpty(applyReqDTO.getGroupIds())) {
            for (Long groupId : applyReqDTO.getGroupIds()) {
                AlgStrategyDeviceGroup association = new AlgStrategyDeviceGroup(null, strategyId, groupId);
                algStrategyDeviceGroupMapper.insert(association);
            }
        }

        return true;
    }

    @Override
    public CommonPage<AlgStrategyVo> list(BasePageReqDTO pageReqDTO) {
        QueryWrapper<AlgStrategy> queryWrapper = new QueryWrapper<>();

        // 排序
        if (StrUtil.isNotEmpty(pageReqDTO.getSortBy())) {
            // 注意：pageReqDTO.getSortBy() 需要是数据库中的列名（驼峰转下划线），请注意防护SQL注入
            if (Objects.equals(BasePageReqDTO.ORDER_DESC, pageReqDTO.getOrder())) {
                queryWrapper.orderByDesc(StrUtil.toUnderlineCase(pageReqDTO.getSortBy()));
            } else {
                queryWrapper.orderByAsc(StrUtil.toUnderlineCase(pageReqDTO.getSortBy()));
            }
        }

        // 关键字模糊查询
        if (StrUtil.isNotEmpty(pageReqDTO.getKeyword())) {
            // TODO: 请根据业务需求，修改需要模糊查询的字段，以下为示例
            // queryWrapper.and(wrapper -> wrapper.like("name", pageReqDTO.getKeyword())
            // .or()
            // .like("description", pageReqDTO.getKeyword()));
        }

        // 根据 page 参数决定是否分页
        if (Boolean.TRUE.equals(pageReqDTO.getPage())) {
            Page<AlgStrategy> page = new Page<>(pageReqDTO.getPageNum(), pageReqDTO.getPageSize());
            Page<AlgStrategy> dbPage = baseMapper.selectPage(page, queryWrapper);
            return CommonPage.restPage(dbPage.convert(this::convertToVo));
        } else {
            List<AlgStrategy> allRecords = baseMapper.selectList(queryWrapper);
            CommonPage<AlgStrategyVo> result = new CommonPage<>();
            result.setList(convertToVoList(allRecords));
            result.setTotal((long) allRecords.size());
            result.setPageNum(1);
            result.setPageSize(allRecords.size());
            result.setTotalPage(1);
            return result;
        }
    }

    @Override
    public AlgStrategyVo getVOById(Long id) {
        // 1. 获取策略基本信息
        AlgStrategy entity = getById(id);
        if (entity == null) {
            return null;
        }

        // 2. 查找关联的算法ID
        QueryWrapper<AlgStrategyAlgorithm> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(AlgStrategyAlgorithm.StrategyId, id);
        List<AlgStrategyAlgorithm> associations = algStrategyAlgorithmMapper.selectList(queryWrapper);

        // 3. 组装VO
        AlgStrategyVo vo = new AlgStrategyVo();
        BeanUtils.copyProperties(entity, vo);

        if (!CollectionUtils.isEmpty(associations)) {
            // 4. 获取算法详情
            List<Long> algorithmIds = associations.stream()
                    .map(AlgStrategyAlgorithm::getAlgorithmId)
                    .collect(Collectors.toList());
            List<AlgAlgorithmVo> algorithms = algAlgorithmService.listByIds(algorithmIds).stream()
                    .map(alg -> {
                        AlgAlgorithmVo algVo = new AlgAlgorithmVo();
                        BeanUtils.copyProperties(alg, algVo);
                        return algVo;
                    }).collect(Collectors.toList());
            vo.setAlgorithms(algorithms);
        } else {
            vo.setAlgorithms(Collections.emptyList());
        }

        return vo;
    }

    @Override
    public List<AlgStrategyVo> convertToVoList(List<AlgStrategy> entityList) {
        if (entityList == null) {
            return null;
        }
        return entityList.stream()
                .map(this::convertToVo)
                .collect(Collectors.toList());
    }

    private AlgStrategyVo convertToVo(AlgStrategy entity) {
        if (entity == null) {
            return null;
        }
        AlgStrategyVo vo = new AlgStrategyVo();
        BeanUtils.copyProperties(entity, vo);
        // 查询创建者名称
        UmsAdmin user = umsAdminMapper.selectById(entity.getCreateBy());
        if (user != null) {
            vo.setCreateName(user.getTrueName());
        }
        return vo;
    }

    @Override
    public AlgStrategy get(Long id) {
        return getById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(Long id) {
        // 检查该策略下是否还配置有规则
        long ruleCount = algStrategyRuleMapper.selectCount(
            new QueryWrapper<AlgStrategyRule>().eq(AlgStrategyRule.StrategyId, id)
        );
        if (ruleCount > 0) {
            Asserts.fail("该策略下仍有关联的规则，禁止删除");
        }
        return removeById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean publish(Long id) {
        // 1. 获取要发布的策略
        AlgStrategy strategy = getById(id);
        if (strategy == null) {
            Asserts.fail("策略不存在");
            return false;
        }

        // 2. 检查该策略是否已经有关联的规则
        QueryWrapper<AlgStrategyAlgorithm> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(AlgStrategyAlgorithm.StrategyId, id);
        long count = algStrategyAlgorithmMapper.selectCount(queryWrapper);
        if (count == 0) {
            Asserts.fail("策略没有关联任何算法，无法发布");
            return false;
        }

        // 3. 设置为已发布状态
        strategy.setPublishStatus(PublishStatusEnum.PUBLISHED.getValue());
        return updateById(strategy);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean unpublish(Long id) {
        // 1. 获取要取消发布的策略
        AlgStrategy strategy = getById(id);
        if (strategy == null) {
            Asserts.fail("策略不存在");
            return false;
        }

        // 2. 检查当前状态
        if (!PublishStatusEnum.isPublished(strategy.getPublishStatus())) {
            // 已经是未发布状态，直接返回成功
            return true;
        }

        // 3. 设置为未发布状态
        strategy.setPublishStatus(PublishStatusEnum.UNPUBLISHED.getValue());
        return updateById(strategy);
    }

    @Override
    public List<AlgStrategyVo> getVOByIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return Collections.emptyList();
        }

        // 1. 批量查询策略基本信息
        List<AlgStrategy> strategies = listByIds(ids);
        if (CollectionUtils.isEmpty(strategies)) {
            return Collections.emptyList();
        }

        // 2. 查询所有策略关联的算法
        QueryWrapper<AlgStrategyAlgorithm> queryWrapper = new QueryWrapper<>();
        queryWrapper.in(AlgStrategyAlgorithm.StrategyId, ids);
        List<AlgStrategyAlgorithm> associations = algStrategyAlgorithmMapper.selectList(queryWrapper);

        // 3. 按策略ID分组
        java.util.Map<Long, List<Long>> strategyAlgorithmMap = associations.stream()
                .collect(Collectors.groupingBy(
                        AlgStrategyAlgorithm::getStrategyId,
                        Collectors.mapping(AlgStrategyAlgorithm::getAlgorithmId, Collectors.toList())));

        // 4. 如果有算法关联，查询算法详情
        final java.util.Map<Long, AlgAlgorithmVo> algorithmVoMap;
        if (!CollectionUtils.isEmpty(associations)) {
            List<Long> algorithmIds = associations.stream()
                    .map(AlgStrategyAlgorithm::getAlgorithmId)
                    .distinct()
                    .collect(Collectors.toList());

            algorithmVoMap = algAlgorithmService.listByIds(algorithmIds).stream()
                    .collect(Collectors.toMap(
                            alg -> alg.getId(),
                            alg -> {
                                AlgAlgorithmVo vo = new AlgAlgorithmVo();
                                BeanUtils.copyProperties(alg, vo);
                                return vo;
                            }));
        } else {
            algorithmVoMap = Collections.emptyMap();
        }

        // 5. 组装并返回结果
        return strategies.stream().map(strategy -> {
            AlgStrategyVo vo = new AlgStrategyVo();
            BeanUtils.copyProperties(strategy, vo);

            // 添加关联的算法
            List<Long> algorithmIds = strategyAlgorithmMap.getOrDefault(strategy.getId(), Collections.emptyList());
            if (!CollectionUtils.isEmpty(algorithmIds)) {
                List<AlgAlgorithmVo> algorithms = algorithmIds.stream()
                        .map(id -> algorithmVoMap.get(id))
                        .filter(Objects::nonNull)
                        .collect(Collectors.toList());
                vo.setAlgorithms(algorithms);
            } else {
                vo.setAlgorithms(Collections.emptyList());
            }

            return vo;
        }).collect(Collectors.toList());
    }
}